import { ColumnHeightOutlined, RedoOutlined } from "@ant-design/icons";
import { Button, Modal, Pagination, Popconfirm, Space, Table, Tooltip } from "antd";
import { SizeType } from "antd/lib/config-provider/SizeContext";
import { useEffect, useState, ReactElement } from "react";
import TableButtons, { ButtonItem } from '../../basic/TableButtons'
import PopoverMenu from "../../basic/PopoverList";
import RemoteSwitch from "../../basic/RemoteSwitch";
import styles from './index.module.sass';
import { local, Mode, remove } from "../../../helper/storage";


const tableScrollConfig = {
    scrollToFirstRowOnChange: true,
    y: '100%'
}

export enum ColumnType {
    Switch = 1
}

export enum ColumnActionType {
    Default = 50,
    Popconfirm,
    Modal
}

/**列渲染类型 */
export enum RenderType {
    /**操作按钮渲染 */
    action = 100,
    /**原入参渲染 */
    original,
    /**默认渲染*/
    default,
    /**自定义渲染 */
    custom,
    /**自定义组件渲染 */
    component,
    /**分组表头渲染 */
    group
}

/**原始组件入参类型 */
// type RTOriginalType = any;
/**默认渲染类型*/
// type RTDefaultType = [string, string, opt?];
/**操作渲染类型*/
// type RTActionType = [[string, Function, string?, any?], ...];
/**分组表头类型*/
// type RTGroupType = [string, [[string, ...], [string, ...]]];
/**自定义渲染类型 */
// type RTCustomType = [string, string, Function];
/**自定义组件渲染类型 */
type RTComponentType = [string, string, ColumnType, any?];

export function renderTypeConfirm(item: any): RenderType {
    if (Array.isArray(item)
        && Array.isArray(item[0])
        && typeof item[0][0] === 'string'
        && typeof item[0][1] === 'function') {
        return RenderType.action;
    } else if (!Array.isArray(item)) {
        return RenderType.original;
    } else if ((item.length === 2
        && typeof item[0] === 'string'
        && typeof item[1] === 'string'
    ) || (item.length === 3
        && typeof item[0] === 'string'
        && typeof item[1] === 'string'
        && typeof item[2] === 'object')) {
        return RenderType.default;
    } else if (item.length === 2
        && typeof item[0] === 'string'
        && Array.isArray(item[1])) {
        return RenderType.group;
    } else if (item.length === 3
        && typeof item[0] === 'string'
        && typeof item[1] === 'string'
        && typeof item[2] === 'function') {
        return RenderType.custom;
    } else if ((item.length === 3
        && typeof item[0] === 'string'
        && typeof item[1] === 'string'
        && typeof item[2] === 'number'
    ) || (item.length === 4
        && typeof item[0] === 'string'
        && typeof item[1] === 'string'
        && ColumnType[item[2]]
        && typeof item[3] === 'object')) {
        return RenderType.component;
    } else {
        return RenderType.default;
    }
}

interface renderParams {
    text: string,
    record: any,
    index: number
}

/**渲染自定义组件函数 */
function switchRTComponent(item: RTComponentType, params: renderParams) {
    let content = (<div></div>);
    const type = item[2];
    const opt = item[3];
    switch (type) {
        case ColumnType.Switch:
            if (opt) {
                const { text: checked }: any = params;
                content = (
                    <RemoteSwitch
                        {...opt}
                        params={params}
                        checked={checked}
                    />
                )
            }
            break;
        default:
            content = (
                <span>没有相关定义的组件</span>
            )
            break;
    }
    return content;
}

/**获取分组表头配置 */
function getColumnGroup([title, children]: [string, any[]]) {
    const column: any = {
        title,
        children: []
    }
    for (let i = 0; i < children.length; i++) {
        const item = children[i];
        let col = createColumn(item);
        column.children.push(col);
    }
    return column;
}

/**解决表格有X轴滚动条且表格数据较少时的展示错位问题 */
function fixTitleMisplaced(tableClassName?: string) {
    if (!tableClassName) {
        return
    }
    const tableContainer = document.querySelector(`.${tableClassName}`);
    /**表格元素。下标0为表格标题， 下标1为表格内容*/
    const tableEleArr = document.querySelectorAll(`.${tableClassName} table`);
    if (tableContainer && tableEleArr.length > 1) {
        /**表格实际高度 */
        let currentHeight = 0;
        tableEleArr.forEach((ele: Element) => currentHeight += ele.clientHeight);
        /**表格容器高度 */
        const containerHeight = tableContainer.clientHeight;
        /**表格标题中的右侧固定元素(包括滚动条占位元素) */
        const tableRightEle: any[] = Array.from(
            tableEleArr[0].querySelectorAll('.ant-table-cell-fix-right')
        ).reverse();
        if (currentHeight < containerHeight) {
            // 表格没有Y轴滚动条
            // 移动距离减少滚动占位元素宽度
            tableRightEle[0] = 0;
        }
        tableRightEle.reduce((total: number | HTMLElement, ele: HTMLElement) => {
            let rightVal = typeof total === 'number' ? total : total.clientWidth;
            ele.style.right = `${rightVal}px`;
            return rightVal + ele.clientWidth;
        })
    }
}

interface TableActionProps {
    /**操作名称 */
    name: string,

    /**点击的回调函数 */
    cb?: Function,

    /**操作按钮的展示类型 */
    type?: ColumnActionType,

    /**操作按钮不同展示类型的扩展项 */
    opt?: any,

    /**判断是否展示操作按钮 */
    handle?: Function

    /**列表文本 */
    text: string,

    /**列表中的项 */
    record: any

    /**禁用表格操作按钮 */
    handleDisable?: boolean
}

const TableAction: React.FC<TableActionProps> = props => {

    function handelClick() {
        props.cb && props.cb(props);
    }

    if (!props.handle || (props.handle && props.handle(props))) {
        return (
            <>
                {!props.type ? (
                    <Button
                        type="link"
                        size='small'
                        onClick={handelClick}
                        disabled={props.opt?.handleDisable && props.opt.handleDisable(props)}
                    >
                        {props.name}
                    </Button>
                ) : (
                    (props.type === ColumnActionType.Popconfirm &&
                        <Popconfirm
                            placement="topRight"
                            onConfirm={handelClick}
                            title={`确认${props.name}吗？`}
                            {...props.opt}
                        >
                            <Button type="link" size='small'>
                                {props.name}
                            </Button>
                        </Popconfirm>
                    ) || (props.type === ColumnActionType.Modal &&
                        <Modal
                            title="Basic Modal"
                            onOk={handelClick}
                        >
                            <span>待完成功能</span>
                        </Modal>
                    )
                )}
            </>
        )
    } else {
        return (<></>)
    }
}

/**
 * 根据配置项创建表格配置
 * 表格操作项解析：[名称, 回调函数, 操作类型, 扩展项, 判断是否显示函数]
 * 其中的：操作类型, 扩展项, 判断是否显示函数。不分先后顺序
 */
function createColumn(item: any) {
    const type = renderTypeConfirm(item);
    let column: any;
    switch (type) {
        case RenderType.action:
            let columnOption: any;
            const actions: any[] = [];
            item.forEach((it: any) => {
                if (Array.isArray(it)) {
                    const [name, cb] = it;
                    let type, opt, handle;
                    for (let index = 2; index < it.length; index++) {
                        const target = it[index];
                        if (ColumnActionType[target]) { type = target }
                        else if (_.isObject(target)) { opt = target }
                        else if (_.isFunction(target)) { handle = target }
                    }
                    actions.push({ name, cb, type, opt, handle });
                } else {
                    columnOption = it;
                }
            });
            column = {
                title: '操作',
                dataIndex: 'table.actions',
                ...columnOption,
                render: (text: string, record: any) => (
                    <Space>
                        {actions.map((action: any) =>
                            <div className={styles.recordAction} key={action.name}>
                                <TableAction {...action} text={text} record={record} />
                            </div>
                        )}
                    </Space>
                )
            };
            break;
        case RenderType.original:
            column = item;
            break;
        case RenderType.default:
            const org = {
                title: item[0],
                dataIndex: item[1],
                key: item[0],
                render: (text: any) => (_.isUndefined(text) || (text === '')) ? '-' : text
            }
            if (item.length === 3) {
                column = {
                    ...org,
                    ...item[2]
                }
            } else {
                column = org
            }
            break;
        case RenderType.custom:
            column = {
                title: item[0],
                dataIndex: item[1],
                render: (text: string, record: any, index: number) => item[2]({ text, record, index })
            };
            break;
        case RenderType.component:
            column = {
                title: item[0],
                dataIndex: item[1],
                render: (text: string, record: any, index: number) => switchRTComponent(item, { text, record, index })
            };
            break;
        case RenderType.group:
            column = getColumnGroup(item);
            break;
        default:
            break;
    }
    return column;
}

export interface PageInfo {
    /**分页页码 */
    pageIndex: number

    /**分页大小 */
    pageSize: number
}

/**当isScrollX为true时，配套的配置项对象 */
interface ScrollXOption {
    /**默认宽度 */
    width?: number

    /**左边固定列数 */
    leftCount?: number

    /**右边固定列数 */
    rightCount?: number
}

export interface GlobalSet {
    /**表格是否不开启选择 */
    isNotSelection?: Boolean

    /**表格是否需要横向滚动条，用于给滚动标题内容添加宽度 */
    isScrollX?: Boolean

    /**表格是否不需要序号 */
    isNotSerialumber?: Boolean

    /**表格左右滚动固定配置 */
    scrollXOption?: ScrollXOption

    /**是否不展示表格工具按钮 */
    isNotToolsButton?: boolean

    /**表格默认展示布局 */
    defaultSize?: 'large' | 'middle' | 'small'

    /**是否在表格底部，分页傍边展示刷新工具按钮 */
    isFooterRefresh?: boolean

    /**是否不显示分页器 */
    isNotPagination?: boolean

    /**分页器尺寸 */
    paginationSize?: 'default' | 'small'

    /**是否设置表格的边框 */
    isSetBordered?: boolean

    /**表格的附加信息，显示在表格上方 */
    extraInfo?: ReactElement | string

    /**是否清除表格选中项 */
    isClearSelect?: boolean

    /**表格请求时清除表格选中 */
    clearSelect?: number
}

interface Props {

    /**表头配置项，二维数组[[title, dataIndex|Function, Function?],...] */
    columns: any[]

    /**数据数组 */
    dataSource?: any[]

    /**表格头部按钮配置项 */
    buttons?: ButtonItem[]

    /**表格查询表单的内容 */
    queryParams?: any

    /**分页控制回调，在回调里控制表格的分页信息 */
    onPagination?: Function

    /**表格刷新的回调 */
    onRefresh?: Function

    /**分页的总数，状态提升 */
    total?: number

    /**分页页码，状态提升 */
    pageIndex?: number

    /**分页大小，状态提升 */
    pageSize?: number

    /**表格数据加载状态 */
    isLoading?: boolean

    /**表格key值 */
    rowKey?: string

    /**表格发生改变时的特殊处理 */
    handleChange?: any

    /**表格的全局属性 */
    global?: GlobalSet
}

const TablePanel: React.FC<Props> = props => {
    console.debug('TablePanel', props)

    const [tableKey] = useState(() => {
        const key = CryptoJS.MD5(JSON.stringify(props.columns.map(item => item[0]))).toString();
        return `TablePanelSize${key}`;
    })

    const [selectedRowKeys, setSelectedRowKeys] = useState<any[]>([]);
    const [selectedRows, setSelectedRows] = useState<any[]>([]);

    const [columns, setColumns] = useState<any[]>([]);
    const [dataSource, setDataSource] = useState<any[]>([]);
    const [buttons, setButtons] = useState<ButtonItem[]>();

    const [isLoading, setIsLoading] = useState(props.isLoading)
    const [rowKey, setRowKey] = useState(props.rowKey || 'id')

    const [size, setSize] = useState<SizeType>(() => {
        let _size = local(tableKey) || props.global?.defaultSize || 'large';
        return _size;
    });

    useEffect(() => {
        let _columns = props.columns.map((item: any, idx: number) => {

            const column = createColumn(item);

            /**固定列的全局配置实现 */
            if (props.global?.isScrollX) {
                if (typeof column.fixed === 'undefined') {
                    if (props.global.scrollXOption?.leftCount) {
                        if (idx < props.global.scrollXOption.leftCount) {
                            column.fixed = 'left';
                        }
                    } else {
                        if (idx === 0) {
                            column.fixed = 'left';
                        }
                    }
                }

                if (props.global.scrollXOption?.rightCount) {
                    if (idx >= props.columns.length - props.global.scrollXOption.rightCount) {
                        column.fixed = 'right';
                    }
                }

                if (typeof column.width === 'undefined') {
                    column.width = props.global.scrollXOption?.width || 150;
                }
            }

            return column;
        });

        /**为表格增加序号一栏 */
        if (!props.global?.isNotSerialumber) {
            const serialumber: any = {
                title: '序号',
                render: (text: any, record: any, index: any) => index + 1,
                width: 60,
                align: 'center'
            }
            if (props.global?.isScrollX || props.global?.scrollXOption) {
                serialumber.fixed = 'left';
            }
            _columns.unshift(serialumber);
        }

        setColumns(_columns);
    }, [props.columns, props.global])

    useEffect(() => {
        if (props.dataSource) {
            setDataSource(props.dataSource);
        }
    }, [props.dataSource])

    useEffect(() => {
        if (props.isLoading !== isLoading) {
            setIsLoading(props.isLoading)
        }
        if (props.rowKey !== rowKey) {
            setRowKey(props.rowKey || 'id');
        }
    }, [props.isLoading, isLoading, props.rowKey, rowKey])

    useEffect(() => {
        if (props.buttons) {
            setButtons(props.buttons);
        }
    }, [props.buttons])

    useEffect(() => {
        if (props.global?.isClearSelect) {
            setSelectedRows([]);
            setSelectedRowKeys([]);
        }
    }, [props.global?.isClearSelect])

    useEffect(() => {
        if (props.global?.clearSelect) {
            setSelectedRows([]);
            setSelectedRowKeys([]);
        }
    }, [props.global?.clearSelect])

    useEffect(() => {
        if (props.global?.isScrollX && dataSource.length > 0) {
            // fixTitleMisplaced(styles.table);
            fixTitleMisplaced();
        }
    }, [dataSource, props.global?.isScrollX])

    function handlePagination(_pageIndex: number, _pageSize?: number) {
        if (props.onPagination) {
            props.onPagination(_pageIndex, _pageSize);
        }
    }

    function handleRefresh() {
        if (props.onRefresh) {
            props.onRefresh();
        }
    }

    /**表格选项的 onChange 事件：保存选中项的 key 和内容 */
    function handleSelectChange(selectKey: any[], selectedRows: any[]) {
        setSelectedRowKeys(selectKey);
        setSelectedRows(selectedRows);
    }

    const sizeMenu = [{
        name: '默认展示',
        action() { setSize('large'); remove(tableKey, Mode.Local); }
    }, {
        name: '中等展示',
        action() { setSize('middle'); local(tableKey, 'middle'); }
    }, {
        name: '紧凑展示',
        action() { setSize('small'); local(tableKey, 'small'); }
    }]

    let rowSelectionConfig: any = {
        selectedRowKeys: selectedRowKeys,
        onChange: handleSelectChange,
        columnWidth: 60
    };

    if (!buttons || props.global?.isNotSelection) {
        rowSelectionConfig = undefined;
    }

    return (
        <article className={styles.wrapper}>

            {(buttons || !props.global?.isNotToolsButton) &&
                <header className={styles.header}>
                    <nav className={styles.buttons}>
                        {buttons &&
                            <TableButtons
                                buttons={buttons}
                                queryParams={props.queryParams}
                                selectedRows={selectedRows}
                            ></TableButtons>
                        }
                    </nav>
                    {!props.global?.isNotToolsButton &&
                        <nav className={styles.action}>
                            <Space>
                                <PopoverMenu title="表格内容密度" list={sizeMenu} >
                                    <Button shape="circle" icon={<ColumnHeightOutlined />} />
                                </PopoverMenu>
                                {props.onRefresh &&
                                    <Tooltip title="刷新">
                                        <Button shape="circle" icon={<RedoOutlined />} onClick={handleRefresh} />
                                    </Tooltip>
                                }
                            </Space>
                        </nav>
                    }
                </header>
            }

            {props.global?.extraInfo &&
                <div className={typeof (props.global?.extraInfo) === 'string' ? styles.extraInfo : ''}>
                    {props.global?.extraInfo}
                </div>
            }

            <Table
                className={styles.table}
                loading={isLoading}
                rowKey={rowKey}
                dataSource={dataSource}
                columns={columns}
                pagination={false}
                size={size}
                rowSelection={rowSelectionConfig}
                scroll={tableScrollConfig}
                bordered={props.global?.isSetBordered}
                onChange={props.handleChange}
            />

            {!props.global?.isNotPagination &&
                <footer className={styles.footer}>
                    <Pagination
                        className={styles.pagination}
                        onChange={handlePagination}
                        total={props.total}
                        showTotal={total => `总 ${total} 条`}
                        current={props.pageIndex}
                        pageSize={props.pageSize}
                        showSizeChanger={true}
                        showQuickJumper={true}
                        size={props.global?.paginationSize}
                    />
                    {props.global?.isFooterRefresh &&
                        <div className={styles.footerRefresh}>
                            <Tooltip title="刷新">
                                <Button shape="circle" icon={<RedoOutlined />} onClick={handleRefresh} />
                            </Tooltip>
                        </div>
                    }
                </footer>
            }

        </article>

    )
}

export default TablePanel;